import dayjs from 'dayjs'

/**
 * 通用工具函数
 */

/**
 * 防抖函数
 * @param fn 需要防抖的函数
 * @param delay 延迟时间
 */
export function debounce<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300
): (...args: Parameters<T>) => void {
  let timer: ReturnType<typeof setTimeout> | null = null
  return function (this: any, ...args: Parameters<T>) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

/**
 * 节流函数
 * @param fn 需要节流的函数
 * @param delay 延迟时间
 */
export function throttle<T extends (...args: any[]) => any>(
  fn: T,
  delay: number = 300
): (...args: Parameters<T>) => void {
  let timer: ReturnType<typeof setTimeout> | null = null
  return function (this: any, ...args: Parameters<T>) {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args)
        timer = null
      }, delay)
    }
  }
}

/**
 * 深拷贝
 * @param obj 要拷贝的对象
 */
export function deepClone<T>(obj: T): T {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj.getTime()) as unknown as T
  if (obj instanceof Array) return obj.map(item => deepClone(item)) as unknown as T
  if (typeof obj === 'object') {
    const cloned = {} as T
    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        cloned[key] = deepClone(obj[key])
      }
    }
    return cloned
  }
  return obj
}

/**
 * 格式化文件大小
 * @param bytes 字节数
 */
export function formatFileSize(bytes: number): string {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 格式化日期
 * @param date 日期
 * @param format 格式
 */
export function formatDate(date: string | number | Date, format: string = 'YYYY-MM-DD HH:mm:ss'): string {
  return dayjs(date).format(format)
}

/**
 * 获取相对时间
 * @param date 日期
 */
export function getRelativeTime(date: string | number | Date): string {
  const now = dayjs()
  const target = dayjs(date)
  const diff = now.diff(target, 'minute')

  if (diff < 1) return '刚刚'
  if (diff < 60) return `${diff}分钟前`
  if (diff < 60 * 24) return `${Math.floor(diff / 60)}小时前`
  if (diff < 60 * 24 * 30) return `${Math.floor(diff / (60 * 24))}天前`
  if (diff < 60 * 24 * 30 * 12) return `${Math.floor(diff / (60 * 24 * 30))}个月前`
  return `${Math.floor(diff / (60 * 24 * 30 * 12))}年前`
}

/**
 * 生成唯一ID
 */
export function generateUUID(): string {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0
    const v = c === 'x' ? r : (r & 0x3 | 0x8)
    return v.toString(16)
  })
}

/**
 * 手机号格式化
 * @param phone 手机号
 */
export function formatPhone(phone: string): string {
  return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
}

/**
 * 邮箱格式化
 * @param email 邮箱
 */
export function formatEmail(email: string): string {
  const [username, domain] = email.split('@')
  const maskedUsername = username.slice(0, 2) + '***' + username.slice(-1)
  return `${maskedUsername}@${domain}`
}

/**
 * 数字千分位格式化
 * @param num 数字
 */
export function formatNumber(num: number): string {
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

/**
 * 获取URL参数
 * @param url URL
 * @param key 参数名
 */
export function getUrlParam(url: string, key: string): string | null {
  const urlObj = new URL(url)
  return urlObj.searchParams.get(key)
}

/**
 * 检查是否为空值
 * @param value 值
 */
export function isEmpty(value: any): boolean {
  if (value === null || value === undefined) return true
  if (typeof value === 'string') return value.trim() === ''
  if (Array.isArray(value)) return value.length === 0
  if (typeof value === 'object') return Object.keys(value).length === 0
  return false
}

/**
 * 数组去重
 * @param arr 数组
 * @param key 去重的键
 */
export function uniqueArray<T>(arr: T[], key?: keyof T): T[] {
  if (!key) {
    return [...new Set(arr)]
  }
  const map = new Map()
  return arr.filter(item => {
    const keyValue = item[key]
    if (map.has(keyValue)) {
      return false
    }
    map.set(keyValue, true)
    return true
  })
}

/**
 * 检查网络状态
 */
export function checkNetworkStatus(): Promise<any> {
  return new Promise((resolve, reject) => {
    uni.getNetworkType({
      success: resolve,
      fail: reject
    })
  })
}

/**
 * 获取系统信息
 */
export function getSystemInfo(): Promise<any> {
  return new Promise((resolve, reject) => {
    uni.getSystemInfo({
      success: resolve,
      fail: reject
    })
  })
}

/**
 * 显示消息提示
 * @param title 提示内容
 * @param icon 图标
 * @param duration 持续时间
 */
export function showToast(
  title: string,
  icon: 'success' | 'error' | 'loading' | 'none' = 'none',
  duration: number = 2000
): void {
  uni.showToast({
    title,
    icon,
    duration
  })
}

/**
 * 显示确认对话框
 * @param content 内容
 * @param title 标题
 */
export function showConfirm(content: string, title: string = '提示'): Promise<boolean> {
  return new Promise((resolve) => {
    uni.showModal({
      title,
      content,
      success: (res: any) => {
        resolve(res.confirm)
      }
    })
  })
}

/**
 * 跳转页面
 * @param url 页面路径
 * @param type 跳转类型
 */
export function navigateTo(
  url: string,
  type: 'navigateTo' | 'redirectTo' | 'reLaunch' | 'switchTab' = 'navigateTo'
): void {
  uni[type]({ url })
}
